/*
 * The contents of this file are subject to the Mozilla Public License
 * Version 1.1 (the "License");  you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 * http//www.mozilla.org/MPL/
 *
 * Software distributed under the License is distributed on an "AS IS" basis,
 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for
 * the specific language governing rights and limitations under the License.
 *
 * The Original Code is ART OWL API.
 *
 * The Initial Developer of the Original Code is University of Roma Tor Vergata.
 * Portions created by University of Roma Tor Vergata are Copyright (C) 2009.
 * All Rights Reserved.
 *
 * The ART OWL API were developed by the Artificial Intelligence Research Group
 * (art.uniroma2.it) at the University of Roma Tor Vergata
 * Current information about the ART OWL API can be obtained at 
 * http://art.uniroma2.it/owlart
 *
 */

package it.uniroma2.art.owlart.models;

import it.uniroma2.art.owlart.exceptions.ModelAccessException;
import it.uniroma2.art.owlart.exceptions.ModelUpdateException;
import it.uniroma2.art.owlart.exceptions.UnsupportedQueryLanguageException;
import it.uniroma2.art.owlart.model.ARTNode;
import it.uniroma2.art.owlart.model.ARTResource;
import it.uniroma2.art.owlart.model.ARTURIResource;
import it.uniroma2.art.owlart.navigation.ARTNodeIterator;
import it.uniroma2.art.owlart.navigation.ARTResourceIterator;
import it.uniroma2.art.owlart.navigation.ARTURIResourceIterator;
import it.uniroma2.art.owlart.query.BooleanQuery;
import it.uniroma2.art.owlart.query.GraphQuery;
import it.uniroma2.art.owlart.query.MalformedQueryException;
import it.uniroma2.art.owlart.query.Query;
import it.uniroma2.art.owlart.query.QueryLanguage;
import it.uniroma2.art.owlart.query.TupleQuery;

/**
 * Interface for basic RDF models<br/>
 * Also, contains extensions to the {@link TripleQueryModel} which allows for more flexible management of
 * query parameters
 * 
 * @author Armando Stellato
 * 
 */
public interface RDFModel extends BaseRDFTripleModel {

	/**
	 * adds a resource with uri=<code>uri</code> to the specified <code>graphs</code><br>
	 * The resource is automatically typized with class <code>cls</code>
	 * 
	 * @param uri
	 * @param cls
	 * @param graphs
	 * @throws ModelUpdateException
	 */
	public abstract void addInstance(String uri, ARTResource cls, ARTResource... graphs)
			throws ModelUpdateException;

	/**
	 * adds a resource with uri=<code>propertyURI</code> as an rdf:Property<br/>
	 * The new property is defined as subproperty of <code>suprtProperty</code> (unless this last is
	 * <code>null</code>)
	 * 
	 * @param propertyURI
	 * @param superProperty
	 * @param graphs
	 * @throws ModelUpdateException
	 */
	public abstract void addProperty(String propertyURI, ARTURIResource superProperty, ARTResource... graphs)
			throws ModelUpdateException;

	/**
	 * adds a type to resource <code>res</code>
	 * 
	 * @param res
	 * @param cls
	 * @param graphs
	 * @throws ModelUpdateException
	 */
	public abstract void addType(ARTResource res, ARTResource cls, ARTResource... graphs)
			throws ModelUpdateException;

	/**
	 * list all properties declared in graphs <code>graphs</code><br/>
	 * If available, reasoning is activated by default, so all kind of properties should be returned by this
	 * method
	 * 
	 * @param graphs
	 * @return
	 * @throws ModelAccessException
	 */
	public abstract ARTURIResourceIterator listProperties(ARTResource... graphs) throws ModelAccessException;

	/**
	 * Contract for this method is:<br/>
	 * If there exist a triple in the specified graphs <code>graphs</code> where a resource with uri=
	 * <code>uri</code> is mentioned, then return that resource, otherwise return <code>null</code>
	 * 
	 * @param uri
	 * @param graphs
	 * @return
	 * @throws ModelAccessException
	 */
	public abstract ARTURIResource retrieveURIResource(String uri, ARTResource... graphs)
			throws ModelAccessException;

	/**
	 * retrieves all classes which are types for resource <code>res</code>
	 * 
	 * @param res
	 * @param inferred
	 * @param graphs
	 * @return
	 * @throws ModelAccessException
	 */
	public ARTResourceIterator listTypes(ARTResource res, boolean inferred, ARTResource... graphs)
			throws ModelAccessException;

	/**
	 * retrieves all instances of class <code>type</code>
	 * 
	 * @param type
	 * @param inferred
	 * @param graphs
	 * @return
	 * @throws ModelAccessException
	 */
	public ARTResourceIterator listInstances(ARTResource type, boolean inferred, ARTResource... graphs)
			throws ModelAccessException;

	/**
	 * list all resources which appear as subjects of statements having given <code>predicate</code> and
	 * <code>object</code>
	 * 
	 * @param predicate
	 * @param object
	 * @param inferred
	 * @return
	 * @throws ModelAccessException
	 */
	public abstract ARTResourceIterator listSubjectsOfPredObjPair(ARTURIResource predicate, ARTNode object,
			boolean inferred, ARTResource... context) throws ModelAccessException;

	/**
	 * list all nodes which appear as objects of statements having given <code>subject</code> and
	 * <code>predicate</code>
	 * 
	 * @param subject
	 * @param predicate
	 * @param inferred
	 * @param contexts
	 * @return
	 * @throws ModelAccessException
	 */
	public abstract ARTNodeIterator listValuesOfSubjPredPair(ARTResource subject, ARTURIResource predicate,
			boolean inferred, ARTResource... contexts) throws ModelAccessException;

	/**
	 * list all uri resources which appear as predicates of statements having given <code>subject</code> and
	 * <code>object</code>
	 * 
	 * @param subject
	 * @param object
	 * @param inferred
	 * @param contexts
	 * @return
	 * @throws ModelAccessException
	 */
	public abstract ARTURIResourceIterator listPredicatesOfSubjObjPair(ARTResource subject, ARTNode object,
			boolean inferred, ARTResource... contexts) throws ModelAccessException;

	/**
	 * checks if resource <code>type</code> is a type for resource <code>res</code>
	 * 
	 * @param res
	 * @param type
	 * @param inferred
	 * @param graphs
	 * @return
	 * @throws ModelAccessException
	 */
	public abstract boolean hasType(ARTResource res, ARTResource type, boolean inferred,
			ARTResource... graphs) throws ModelAccessException;

	/**
	 * removes the rdf:type relationship between <code>res</code> and <code>cls</code>
	 * 
	 * @param res
	 * @param cls
	 * @param graphs
	 * @throws ModelUpdateException
	 */
	public abstract void removeType(ARTResource res, ARTResource cls, ARTResource... graphs)
			throws ModelUpdateException;

	/**
	 * renames a resource (which can either be a class or an individual)
	 * 
	 * @param res
	 * @param newURI
	 * @throws ModelUpdateException
	 */
	public abstract void renameIndividual(ARTURIResource res, String newURI) throws ModelUpdateException;

	/**
	 * renames a property
	 * 
	 * @param res
	 * @param newLocalName
	 * @throws ModelUpdateException
	 */
	public abstract void renameProperty(ARTURIResource res, String newLocalName) throws ModelUpdateException;

	/**
	 * checks that resource <code>prop</code> is a property<br/>
	 * If available, reasoning is activated by default, so all kind of properties should be properly checked
	 * by this method
	 * 
	 * @param prop
	 * @param graphs
	 * @return
	 * @throws ModelAccessException
	 */
	public abstract boolean isProperty(ARTResource prop, ARTResource... graphs) throws ModelAccessException;

	// EXTENSIONS TO TRIPLE QUERY MODEL

	// Query creation

	/**
	 * as for {@link TripleQueryModel#createQuery(QueryLanguage, String, String)} with QueryLanguage=
	 * {@link QueryLanguage#SPARQL} and baseuri set on the baseuri of the ontology managed by this model
	 * 
	 * @param query
	 * @return
	 * @throws UnsupportedQueryLanguageException
	 * @throws ModelAccessException
	 * @throws MalformedQueryException
	 */
	public Query createQuery(String query) throws UnsupportedQueryLanguageException, ModelAccessException,
			MalformedQueryException;

	/**
	 * as for {@link TripleQueryModel#createQuery(QueryLanguage, String, String)} with QueryLanguage=
	 * {@link QueryLanguage#SPARQL}
	 * 
	 * @param query
	 * @param baseURI
	 * @return
	 * @throws UnsupportedQueryLanguageException
	 * @throws ModelAccessException
	 * @throws MalformedQueryException
	 */
	public Query createQuery(String query, String baseURI) throws UnsupportedQueryLanguageException,
			ModelAccessException, MalformedQueryException;

	/**
	 * as for {@link TripleQueryModel#createQuery(QueryLanguage, String, String)} with baseuri set on the
	 * baseuri of the ontology managed by this model
	 * 
	 * @param ql
	 * @param query
	 * @return
	 * @throws UnsupportedQueryLanguageException
	 * @throws ModelAccessException
	 * @throws MalformedQueryException
	 */
	public Query createQuery(QueryLanguage ql, String query) throws UnsupportedQueryLanguageException,
			ModelAccessException, MalformedQueryException;

	// Boolean Query creation

	/**
	 * as for {@link TripleQueryModel#createBooleanQuery(QueryLanguage, String, String)} with QueryLanguage=
	 * {@link QueryLanguage#SPARQL} and baseuri set on the baseuri of the ontology managed by this model
	 * 
	 * @param query
	 * @return
	 * @throws UnsupportedQueryLanguageException
	 * @throws ModelAccessException
	 * @throws MalformedQueryException
	 */
	public BooleanQuery createBooleanQuery(String query) throws UnsupportedQueryLanguageException,
			ModelAccessException, MalformedQueryException;

	/**
	 * as for {@link TripleQueryModel#createBooleanQuery(QueryLanguage, String, String)} with QueryLanguage=
	 * {@link QueryLanguage#SPARQL}
	 * 
	 * @param query
	 * @param baseURI
	 * @return
	 * @throws UnsupportedQueryLanguageException
	 * @throws ModelAccessException
	 * @throws MalformedQueryException
	 */
	public BooleanQuery createBooleanQuery(String query, String baseURI)
			throws UnsupportedQueryLanguageException, ModelAccessException, MalformedQueryException;

	/**
	 * as for {@link TripleQueryModel#createBooleanQuery(QueryLanguage, String, String)} with baseuri set on
	 * the baseuri of the ontology managed by this model
	 * 
	 * @param ql
	 * @param query
	 * @return
	 * @throws UnsupportedQueryLanguageException
	 * @throws ModelAccessException
	 * @throws MalformedQueryException
	 */
	public BooleanQuery createBooleanQuery(QueryLanguage ql, String query)
			throws UnsupportedQueryLanguageException, ModelAccessException, MalformedQueryException;

	// Graph Query creation

	/**
	 * as for {@link TripleQueryModel#createGraphQuery(QueryLanguage, String, String)} with QueryLanguage=
	 * {@link QueryLanguage#SPARQL} and baseuri set on the baseuri of the ontology managed by this model
	 * 
	 * @param query
	 * @return
	 * @throws UnsupportedQueryLanguageException
	 * @throws ModelAccessException
	 * @throws MalformedQueryException
	 */
	public GraphQuery createGraphQuery(String query) throws UnsupportedQueryLanguageException,
			ModelAccessException, MalformedQueryException;

	/**
	 * as for {@link TripleQueryModel#createGraphQuery(QueryLanguage, String, String)} with QueryLanguage=
	 * {@link QueryLanguage#SPARQL}
	 * 
	 * @param query
	 * @param baseURI
	 * @return
	 * @throws UnsupportedQueryLanguageException
	 * @throws ModelAccessException
	 * @throws MalformedQueryException
	 */
	public GraphQuery createGraphQuery(String query, String baseURI)
			throws UnsupportedQueryLanguageException, ModelAccessException, MalformedQueryException;

	/**
	 * as for {@link TripleQueryModel#createGraphQuery(QueryLanguage, String, String)} with baseuri set on the
	 * baseuri of the ontology managed by this model
	 * 
	 * @param ql
	 * @param query
	 * @return
	 * @throws UnsupportedQueryLanguageException
	 * @throws ModelAccessException
	 * @throws MalformedQueryException
	 */
	public GraphQuery createGraphQuery(QueryLanguage ql, String query)
			throws UnsupportedQueryLanguageException, ModelAccessException, MalformedQueryException;

	// tuple Query creation

	/**
	 * as for {@link TripleQueryModel#createTupleQuery(QueryLanguage, String, String)} with QueryLanguage=
	 * {@link QueryLanguage#SPARQL} and baseuri set on the baseuri of the ontology managed by this model
	 * 
	 * @param query
	 * @return
	 * @throws UnsupportedQueryLanguageException
	 * @throws ModelAccessException
	 * @throws MalformedQueryException
	 */
	public TupleQuery createTupleQuery(String query) throws UnsupportedQueryLanguageException,
			ModelAccessException, MalformedQueryException;

	/**
	 * as for {@link TripleQueryModel#createTupleQuery(QueryLanguage, String, String)} with QueryLanguage=
	 * {@link QueryLanguage#SPARQL}
	 * 
	 * @param query
	 * @param baseURI
	 * @return
	 * @throws UnsupportedQueryLanguageException
	 * @throws ModelAccessException
	 * @throws MalformedQueryException
	 */
	public TupleQuery createTupleQuery(String query, String baseURI)
			throws UnsupportedQueryLanguageException, ModelAccessException, MalformedQueryException;

	/**
	 * as for {@link TripleQueryModel#createTupleQuery(QueryLanguage, String, String)} with baseuri set on the
	 * baseuri of the ontology managed by this model
	 * 
	 * @param ql
	 * @param query
	 * @return
	 * @throws UnsupportedQueryLanguageException
	 * @throws ModelAccessException
	 * @throws MalformedQueryException
	 */
	public TupleQuery createTupleQuery(QueryLanguage ql, String query)
			throws UnsupportedQueryLanguageException, ModelAccessException, MalformedQueryException;

}
